package com.xiaoyu.lanling.feature.voicecall.data

import `in`.srain.cube.request.FailData
import `in`.srain.cube.request.JsonData
import `in`.srain.cube.request.RequestDefaultHandler
import `in`.srain.cube.util.CLog
import `in`.srain.cube.util.internal.AppCallback
import `in`.srain.cube.util.internal.AppConsumer
import com.xiaoyu.base.data.UserData
import com.xiaoyu.base.event.NoReceiverJsonEvent
import com.xiaoyu.base.net.RequestCreator
import com.xiaoyu.im.ChatToken
import com.xiaoyu.lanling.common.config.HttpConfig
import com.xiaoyu.lanling.event.voicecall.HangupEvent
import com.xiaoyu.lanling.feature.im.request.MessageRequestBuilder
import com.xiaoyu.lib_av.datamodel.AVTokenInfo
import com.xiaoyu.lib_av.datamodel.AVTokenInfo.Companion.fromJson
import com.xiaoyu.lib_av.manager.AgoraManager
import com.xiaoyu.lib_av.proxy.AgoraAbstractProxy

object CallData {

    object ActionType {
        const val ACCEPT = "accept"
        const val REJECT = "reject"
        const val CANCEL = "cancel"
        const val HANGUP = "hangup"
    }

    @JvmField
    public var sLoginRunnable = Runnable {
        if (!UserData.getInstance().hasLogin()) {
            CLog.w(AgoraManager.TAG, "login failure: user has not login")
            return@Runnable
        }
        getTokenFromServer(object : AppCallback<AVTokenInfo?> {
            override fun onSuccess(tokenInfo: AVTokenInfo) {
                AgoraManager.getInstance().login(tokenInfo)
            }

            override fun onError(e: Throwable) {
                AgoraManager.getInstance().getTokenFromServerDelay()
            }
        })
    }

    fun establishConnection(fromUid: String?) {
        RequestCreator.create<NoReceiverJsonEvent>(Any(), NoReceiverJsonEvent::class.java)
                .setRequestUrl(HttpConfig.AV_ESTABLISH_CONNECTION)
                .addPostData("fromUid", fromUid)
                .enqueue()
    }

    fun hangup(fuid: String?, type: String?) {
        RequestCreator.create<HangupEvent>(Any(), HangupEvent::class.java)
                .setRequestUrl(HttpConfig.AV_HANGUP)
                .addPostData("anotherUid", fuid)
                .addPostData("typeForLog", type)
                .enqueue()
    }

    fun getCallParams(toUid: String?, runnable: AppConsumer<JsonData>) {
        RequestCreator.create<JsonData>(JsonData::class.java)
                .setRequestUrl(HttpConfig.AV_GET_CALL_PARAM)
                .addQueryData("toUid", toUid)
                .setRequestHandler(object : RequestDefaultHandler<JsonData, JsonData>() {
                    override fun processOriginData(originData: JsonData): JsonData {
                        return originData.optJson("data")
                    }

                    override fun onRequestFinish(data: JsonData) {
                        runnable.accept(data)
                    }

                    override fun onRequestFail(failData: FailData) {
                        super.onRequestFail(failData)
                        runnable.accept(JsonData.newMap())
                    }
                })
                .enqueue()
    }

    private fun getTokenFromServer(callback: AppCallback<AVTokenInfo?>) {
        RequestCreator.create(AVTokenInfo::class.java)
                .setRequestUrl(HttpConfig.AV_GET_TOKEN)
                .setRequestHandler(object : RequestDefaultHandler<AVTokenInfo, JsonData>() {

                    override fun processOriginData(originData: JsonData): AVTokenInfo {
                        val jsonData: JsonData = originData.optJson("data")
                        return fromJson(jsonData)
                    }

                    override fun onRequestFinish(tokenInfo: AVTokenInfo) {
                        if (tokenInfo.isEmpty) {
                            CLog.e(AgoraAbstractProxy.TAG, "login failure, tokenInfo is empty")
                            callback.onError(IllegalArgumentException("lib-av login failure, tokenInfo is empty"))
                            return
                        }
                        callback.onSuccess(tokenInfo)
                    }

                    override fun onRequestFail(failData: FailData) {
                        callback.onError(IllegalStateException("lib-av request call token failure"))
                    }
                })
                .enqueue()
    }

    fun sendVoiceStatusMessageForCancel(uid: String) {
        sendCallStatusMessage(uid, "cancel", 0, "")
    }

    fun sendVoiceStatusMessageForReject(uid: String) {
        sendCallStatusMessage(uid, "reject", 0, "")
    }

    fun sendVoiceStatusMessageForCall(uid: String, callDuration: Long, fromType: String) {
        sendCallStatusMessage(uid, "call", callDuration, fromType)
    }

    private fun sendCallStatusMessage(uid: String, type: String, callDuration: Long, fromType: String) {
        MessageRequestBuilder.newBuilder(ChatToken.forUid(uid), fromType)
                .callStatus(type, callDuration)
                .buildAndSend()
    }
}